package com.alipay.rebate.shop.configuration.shiro.realm;

import com.alipay.rebate.shop.configuration.shiro.JwtCredentialsMatcher;
import com.alipay.rebate.shop.constants.StatusCode;
import com.alipay.rebate.shop.constants.UserContant;
import com.alipay.rebate.shop.exceptoin.BusinessException;
import com.alipay.rebate.shop.helper.SpringBeanHelper;
import com.alipay.rebate.shop.utils.JwtUtils;
import com.alipay.rebate.shop.configuration.shiro.token.JWTToken;
import com.alipay.rebate.shop.pojo.user.customer.UserDto;
import com.alipay.rebate.shop.service.common.UserService;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;


/**
 * 自定义身份认证
 * 基于HMAC（ 散列消息认证码）的控制域
 */

public class JWTShiroRealm extends AuthorizingRealm {
	private final Logger logger = LoggerFactory.getLogger(JWTShiroRealm.class);

    protected UserService userService;

    public JWTShiroRealm(UserService userService){
        this.userService = userService;
        this.setCredentialsMatcher(new JwtCredentialsMatcher());
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 认证信息.(身份验证) : Authentication 是用来验证用户身份
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {    

        logger.debug("Get into JWTShiroRealm");
        JWTToken jwtToken = (JWTToken) authcToken;
        logger.debug("jwtToken is : {}",jwtToken);
        String token = jwtToken.getToken();
        logger.debug("jwtToken is : {}",jwtToken);

        if(StringUtils.isEmpty(token)){
            throw new BusinessException("token不能为空",StatusCode.TOKEN_NULL);
        }

        // 如果token 过期，那么抛出异常
        if(JwtUtils.isTokenExpired(token)){
            throw new BusinessException(StatusCode.TOKEN_EXPIRE);
        }

        String loginType = JwtUtils.getLoginType(token);
        logger.debug("loginType is : {}",loginType);
        // app 用户登陆
        if(UserContant.APP_LOGIN_TYPE.equals(loginType)){
            return dealWithAppLogic(token);
        }
        // pc 后台登陆
        if(UserContant.PC_LOGIN_TYPE.equals(loginType)){
            return dealWithPCLogic(token);
        }

        return null;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        UserDto user = (UserDto) principals.getPrimaryPrincipal();
        List<String> roles = user.getRoles();
        logger.debug("user original roles is : {}",roles);
        if(roles == null) {
            roles = userService.getUserRoles(user.getUserId());
            user.setRoles(roles);
        }
        if (roles != null)
            simpleAuthorizationInfo.addRoles(roles);
        logger.debug("user final roles is : {}",roles);

        return simpleAuthorizationInfo;
    }

    private AuthenticationInfo dealWithAppLogic(String token){
        logger.debug("app login type");
        userService = SpringBeanHelper.getCustomerUserService();
        UserDto user = userService.getJwtTokenInfo(JwtUtils.getUserId(token));
        logger.debug("UserDto is : {}",user);
        if(user == null)
            throw new BusinessException("用户不存在",StatusCode.USER_NOT_EXISTS);
        if(UserContant.USER_STATUS_BLACK.equals(user.getUserStatus())){
            throw new BusinessException(StatusCode.USER_IN_BLACK_LIST);
        }
        if(UserContant.USER_STATUS_LOGOFF.equals(user.getUserStatus())){
            throw new BusinessException("账号不存在",StatusCode.USER_NOT_EXISTS);
        }
        return new SimpleAuthenticationInfo(user, user.getSalt(), "jwtRealm");
    }

    private AuthenticationInfo dealWithPCLogic(String token){
        logger.debug("pc login type");
        userService = SpringBeanHelper.getAdminUserService();
        UserDto user = userService.getJwtTokenInfo(JwtUtils.getUserId(token));
        logger.debug("UserDto is : {}",user);
        if(user == null)
            throw new BusinessException("用户不存在",StatusCode.USER_NOT_EXISTS);
        return new SimpleAuthenticationInfo(user, user.getSalt(), "jwtRealm");
    }
}
